﻿using System.Linq;
using System.Threading.Tasks;

namespace KinonekoSoftware.Studio.Components
{
    public delegate string ObjectNameSelector(object instance);

    public sealed class ObjectSelectorViewModel : SelectionDialog<object>
    {
        private static string DefaultObjectNameSelector(object instance) => instance?.ToString();

        public static async Task<Result<T>> Single<T>(IEnumerable<T> collection, ObjectNameSelector nameSelector = null, object defaultValue = null) where T : class
        {
            var context = new DialogContext();

            context.Set<IEnumerable<object>>("c", collection);
            context.Set("n", nameSelector ?? DefaultObjectNameSelector);
            context.Set("d", defaultValue);
            context.Set("m", false);

            var r = await Dialog((ISelectionDialog<object>)new ObjectSelectorViewModel(), context);

            if (r.IsFinished && r.Value.FirstOrDefault() is T value)
            {
                return Result<T>.Success(value);
            }

            return Result<T>.Failed(r.Reason);
        }

        public static async Task<Result<IList<T>>> Multiple<T>(IEnumerable<T> collection, ObjectNameSelector nameSelector = null, object defaultValue = null) where T : class
        {
            var context = new DialogContext();

            context.Set<IEnumerable<object>>("c", collection);
            context.Set("n", nameSelector ?? DefaultObjectNameSelector);
            context.Set("d", defaultValue);
            context.Set("m", true);

            var r   = await Dialog((ISelectionDialog<object>)new ObjectSelectorViewModel(), context);
            var val = r.Value;

            if (r.IsFinished)
            {
                var tList      = val.Cast<T>().ToList();
                return Result<IList<T>>.Success(tList);
            }

            return Result<IList<T>>.Failed(r.Reason);
        }

        private ObjectNameSelector _selector;

        protected override bool OnReceive(DialogContext context)
        {
            if (context.Has("c") && context.Has("n") && context.Has("m"))
            {
                _selector           = context.GetObject<ObjectNameSelector>("n");
                IsMultipleSelection = context.GetBoolean("m");
                var c = context.GetObject<IEnumerable<object>>("c");
                Collection.AddMany(c, true);
            }


            if (context.Has("d"))
            {
                SetSelectedItem(context.GetObject("d"));
            }

            return base.OnReceive(context);
        }

        public ObjectNameSelector Selector => _selector;
    }
}